﻿using Asp.Versioning;
using FlyingEye.DeviceMaintenance;
using FlyingEye.DeviceMaintenance.Repositories;
using FlyingEye.DeviceMaintenanceServices;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories;

namespace FlyingEye.Controllers
{
    [Route("api/device-ops-service/v{version:apiVersion}/device-parts")]
    [ApiVersion("1.0")]
    [ControllerName("DevicePart")]
    [Authorize]
    public class DevicePartController : DefaultController
    {
        private readonly DevicePartService _devicePartService;

        private readonly MaintenanceRecordService _maintenanceRecordService;

        private readonly DevicePartCheckItemService _devicePartCheckItemService;

        private readonly IDevicePartRepository _devicePartRepository;

        private readonly IMaintenanceRecordRepository _maintenanceRecordRepository;

        private readonly IDevicePartCharacteristicRepository _devicePartCharacteristicRepository;


        public DevicePartController(
            ILogger<DevicePartController> logger,
            DevicePartService devicePartService,
            MaintenanceRecordService maintenanceRecordService,
            IDevicePartCheckItemRepository devicePartCheckItemRepository,
            DevicePartCheckItemService devicePartCheckItemService,
            IDevicePartRepository devicePartRepository,
            IMaintenanceRecordRepository maintenanceRecordRepository,
            IDevicePartCharacteristicRepository devicePartCharacteristicRepository)
        {
            _devicePartService = devicePartService;
            _maintenanceRecordService = maintenanceRecordService;
            _devicePartCheckItemService = devicePartCheckItemService;
            _devicePartRepository = devicePartRepository;
            _maintenanceRecordRepository = maintenanceRecordRepository;
            _devicePartCharacteristicRepository = devicePartCharacteristicRepository;
        }

        [HttpGet("{id}/characteristics")]
        public async Task<ActionResult<List<DevicePartCharacteristicResponse>>> GetCharacteristicsAsync(Guid id)
        {
            return await this.GetInvokeAsync(async () =>
            {
                var list = await _devicePartCharacteristicRepository.GetListAsync(item => item.DevicePartId == id);
                return ObjectMapper.Map<List<DevicePartCharacteristicModel>, List<DevicePartCharacteristicResponse>>(list);
            });
        }

        [HttpGet("{id}/last-record")]
        public async Task<ActionResult<MaintenanceRecordResponse?>> GetLastRecordAsync(Guid id)
        {
            return await this.GetInvokeAsync(async () =>
            {
                var query = await _maintenanceRecordRepository.GetQueryableAsync();

                var model = await query.Where(e => !e.IsActive && e.DevicePartId == id)
                .OrderByDescending(e => e.CreationTime)
                .FirstOrDefaultAsync();

                if (model == null)
                {
                    return null;
                }

                return ObjectMapper.Map<MaintenanceRecordModel, MaintenanceRecordResponse>(model);
            });
        }

        [HttpGet("{id}/active-record")]
        public async Task<ActionResult<MaintenanceRecordResponse?>> GetActiveRecordAsync(Guid id)
        {
            return await this.GetInvokeAsync(async () =>
            {
                var record = await _maintenanceRecordRepository.FindAsync(x => x.DevicePartId == id && x.IsActive);

                if (record == null)
                {
                    return null;
                }

                return ObjectMapper.Map<MaintenanceRecordModel, MaintenanceRecordResponse>(record);
            });
        }

        [HttpGet]
        public async Task<ActionResult<List<DevicePartResponse>>> GetListAsync()
        {
            return await this.GetInvokeAsync(async () =>
            {
                var list = await _devicePartRepository.GetListAsync();

                return ObjectMapper.Map<List<DevicePartModel>, List<DevicePartResponse>>(list);
            });
        }

        [HttpGet("{partId}/check-items")]
        public async Task<ActionResult<List<DevicePartCheckItemResponse>>> GetCheckItemsAsync(Guid partId)
        {
            return await GetInvokeAsync(async () =>
            {
                return await _devicePartCheckItemService.GetByDevicePartAsync(partId);
            });
        }

        [HttpGet("{partId}/records")]
        public async Task<ActionResult<List<MaintenanceRecordResponse>>> GetRecordsAsync(Guid partId)
        {
            return await GetInvokeAsync(async () =>
            {
                return await _maintenanceRecordService.GetByDevicePartAsync(partId);
            });
        }

        /// <summary>
        /// 业务动作
        /// </summary>
        [HttpPost("{id}/start-maintaining")]
        public async Task<OkResult> StartMaintainingAsync(Guid id)
        {
            return await ActionInvokeAsync(async () =>
            {
                await _devicePartService.StartMaintainingAsync(id);
            });
        }

        /// <summary>
        /// 业务动作
        /// </summary>
        [HttpPost("{id}/end-maintaining")]
        public async Task<OkResult> EndMaintainingAsync(Guid id)
        {
            return await ActionInvokeAsync(async () =>
            {
                await _devicePartService.EndMaintainingAsync(id);
            });
        }

        /// <summary>
        /// 业务动作
        /// </summary>
        [HttpPost("{id}/cancel-maintaining")]
        public async Task<OkResult> CancelMaintainingAsync(Guid id, [FromBody] CancelRequest cancelRequest)
        {
            return await ActionInvokeAsync(async () =>
            {
                await _devicePartService.CancelMaintainingAsync(id, cancelRequest.Reason);
            });
        }

        /// <summary>
        /// 业务动作
        /// </summary>
        [HttpPost("{id}/maintenance-step")]
        public async Task<OkResult> UpdateMaintenanceStepAsync(Guid id, [FromBody] StepActionRequest stepAction)
        {
            return await ActionInvokeAsync(async () =>
            {
                await _devicePartService.UpdateMaintenanceStepAsync(id, stepAction);
            });
        }

        [HttpDelete("{id}")]
        public async Task<NoContentResult> DeleteAsync(Guid id)
        {
            return await DeleteInvokeAsync(async () =>
            {
                await _devicePartService.DeleteAsync(id);
            });
        }

        [HttpPut]
        public async Task<ActionResult<DevicePartResponse>> UpdateAsync([FromBody] UpdateDevicePartRequest devicePart)
        {
            return await PatchInvokeAsync(async () =>
            {
                return await _devicePartService.UpdateAsync(devicePart);
            });
        }

        [HttpPost]
        public async Task<ActionResult<DevicePartResponse>> InsertAsync([FromBody] CreateDevicePartRequest devicePart)
        {
            return await InsertInvokeAsync(async () =>
            {
                return await _devicePartService.InsertAsync(devicePart);
            }, "GetByPartId", (result) => new { id = result.Id });
        }

        [HttpGet("{id}", Name = "GetByPartId")]
        public async Task<ActionResult<DevicePartResponse>> GetAsync(Guid id)
        {
            return await GetInvokeAsync(async () =>
            {
                return await _devicePartService.GetAsync(id);
            });
        }
    }
}
